package com.hanyxx.redis;

import org.junit.After;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;

import java.util.*;

/**
 * @author layman
 * @description: redis简单测试类
 * @date 2021/2/4
 */
public class RedisTest {
    private static Jedis jedis = new Jedis("127.0.0.1",6379);
    private static byte[] bt = "关系型数据库".getBytes();
    private static byte[] mysqlByte = "MySQL数据库".getBytes();
    private static byte[] bestByte = "是最好用的数据库".getBytes();
    //jedis连接池
    static{
        JedisPoolConfig config = new JedisPoolConfig();
        //最多有200个空闲
        config.setMaxIdle(200);
        config.setMaxTotal(500);
        //最大等待时间
        config.setMaxWaitMillis(10*1000);
        //获得jedis实例是否检查连接可用性（ping），true表示得到的jedis实例均可用
        config.setTestOnBorrow(true);
    }
    @After
    public void close(){
        //归还至连接池
        jedis.close();
    }
    /**
     * redis是一款高性能的NOSQL系列的非关系型数据库
     * redis存储的是：key,value格式的数据，其中key都是字符串，value有5种不同的数据结构
     * value的数据结构：
             1) 字符串类型 string
             2) 哈希类型 hash ： map<String><String> 格式或者byte[]数组格式
             3) 列表类型 list ： LinkedList格式,支持重复元素(链表)
             4) 集合类型 set  ： 不允许重复元素
             5) 有序集合类型 SortedSet：不允许重复元素，且元素有顺序
     */
    public static void main(String[] args) {
        jedis.del("name","username","age");
    }
    /**
     * 设置字符串类型数据
     */
    @Test
    public void putString(){
        jedis.set("name","菠菜饭团");
        jedis.set("username","饭团");
        jedis.set("age","18");
    }
    /**
     * 获取字符串类型数据
     */
    @Test
    public void getString(){
        String name = jedis.get("name");
        String username = jedis.get("username");
        String age = jedis.get("age");
        System.out.println(name+":"+username+":"+age);
    }
    /**
     * 设置hash数据
     */
    @Test
    public void setHash(){
        //演示添加map数据，只能为<String,String>格式
        Map<String,String> map= new HashMap<>();
        //map key不允许重复，后添加的数据会覆盖之前的数据
        map.put("address","中国江苏");
        map.put("email","fantuan@email.com");
        map.put("phone","66778899");
        //最终显示 123456
        map.put("phone","123456");
        jedis.hset("myHash",map);
        jedis.hset("myHash","lastName","goodman");
        //演示添加byte[]数据
        Map<byte[],byte[]> byteMap= new HashMap<>();
        byteMap.put(mysqlByte,bestByte);
        jedis.hset(bt,byteMap);
    }
    /**
     * 获取hash数据
     */
    @Test
    public void getHash(){
        String email = jedis.hget("myHash", "email");
        String lastName = jedis.hget("myHash", "lastName");
        byte[] bytes = jedis.hget(bt, mysqlByte);
        System.out.println(email);
        System.out.println(lastName);
        System.out.println(new String(bytes));
    }
    /**
     * 设置list数据：允许重复
     */
    @Test
    public void setList(){
        //从左边添加
        jedis.lpush("myList","first","second","three");
        //从右边添加
        jedis.rpush("myList","first","second","three");
        //此时数据顺序为："three"，"second","first", "first","second","three"
    }
    /**
     * 获取list数据
     */
    @Test
    public void getList(){
        List<String> myList = jedis.lrange("myList", 0, -1);
        //[three, second, first, first, second, three]
        System.out.println(myList);
        //删除弹出列表最左边的元素，并将其返回
        String l_data = jedis.lpop("myList");
        //three
        System.out.println(l_data);
        String r_data = jedis.rpop("myList");
        System.out.println(r_data);
    }
    /**
     * 存储sortedSet:不允许重复，且有序
     */
    @Test
    public void setSortedSet(){
        jedis.zadd("mySortedSet",20D,"芹菜饭团");
        Map<String,Double> sortedSetMap = new HashMap<>();
        sortedSetMap.put("花菜饭团",60D);
        sortedSetMap.put("紫菜饭团",55D);
        sortedSetMap.put("雪菜饭团",99D);
        jedis.zadd("mySortedSet",sortedSetMap);
    }
    @Test
    public void getSortedSet(){
        Set<String> set = jedis.zrange("mySortedSet", 0, -1);
        System.out.println(set);
        //从sortedSet中删除指定的值
        jedis.zrem("mySortedSet", "花菜饭团");
    }
    @Test
    public void deleteKey(){
        //删除整个key
        jedis.del("username");
        //删除key中的某个属性
        jedis.hdel("myHash","lastName");
        jedis.del(bt);
    }
    /**
    * redis事务
    */
    @Test
    public void testTransaction(){
        //开启事务
        Transaction transaction = jedis.multi();
        //进入执行队列
        transaction.set("name","layman");
        transaction.set("age","18");
        //执行事务
        //transaction.exec();
        //取消事务
        transaction.discard();
    }
    /**
     * redis监控(模拟监控)
     */
    @Test
    public boolean testWatch(){
        //可用余额
        int balance;
        //欠额
        int debt;
        //实刷额度
        int actualAmount = 20;
        jedis.watch("balance");
        balance = Integer.parseInt(jedis.get("balance"));
        if(balance < actualAmount){
            //余额不足，放弃监控，返回失败
            jedis.unwatch();
            System.out.println("余额不足，刷卡失败");
            return false;
        }
        //信用卡额度和欠款总和应当为定值，此时使用事务进行控制
        Transaction multi = jedis.multi();
        //可用余额减少
        multi.decrBy("balance",actualAmount);
        //欠额增加
        multi.incrBy("debt",actualAmount);
        //执行
        try {
            multi.exec();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * redis主从复制
     */
    @Test
    public void testMasterAndSlave(){
        Jedis jedis_slave = new Jedis("127.0.0.1",6380);
        jedis_slave.slaveof("127.0.0.1",6379);
        jedis.set("name","layman");

        String name = jedis_slave.get("name");
        System.out.println(name);
    }
}